package com.qy.securitydemo.config;

import com.qy.securitydemo.service.CustomUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author HXB
 * @Title:
 * @Package
 * @Description:
 * @date 2019-11-0811:26
 */

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 注册CustomUserService的bean
     *
     * @return
     */
    @Bean
    UserDetailsService customUserService() { //2
        return new CustomUserService();
    }

    /**
     * 添加我们自定义的user UserDetails
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.userDetailsService(customUserService()); //3
        //注入userDetailsService的实现类
        auth.userDetailsService(customUserService()).passwordEncoder(new BCryptPasswordEncoder());

    }

    /**
     * @param http
     * @throws Exception
     */
    //1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成，相关配置重写对应 方法即可。
    //2.我们在这里注册CustomUserService的Bean，然后通过重写configure方法添加我们自定义的认证方式。
    //3.在configure(HttpSecurity http)方法中，我们设置了登录页面，而且登录页面任何人都可以访问，然后设置了登录失败地址，也设置了注销请求，注销请求也是任何人都可以访问的。
    //4.permitAll表示该请求任何人都可以访问，.anyRequest().authenticated(),表示其他的请求都必须要有权限认证。
    //5.这里我们可以通过匹配器来匹配路径，比如antMatchers方法，假设我要管理员才可以访问admin文件夹下的内容，我可以这样来写：.antMatchers("/admin/**").hasRole("ROLE_ADMIN")，也可以设置admin文件夹下的文件可以有多个角色来访问，写法如下：.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")
    //6.可以通过hasIpAddress来指定某一个ip可以访问该资源,假设只允许访问ip为210.210.210.210的请求获取admin下的资源，写法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210")
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated() //4  所有请求必须要登录后才能认证
                .and()
                .formLogin()
                .loginPage("/login")
                .failureUrl("/login?error")//登录失败访问的页面
                .permitAll() //5 定制登录页面行为登录页面可以任意访问
                .and()
                .logout().permitAll() //6 注销可以任意访问
                .and().formLogin();
        http.csrf().disable();


    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        web.ignoring().antMatchers("/css/**", "/css/**", "/images/**");//静态资源访问
    }


}